package com.ts.api.module.api.service.impl;

import com.gitee.apanlh.util.algorithm.digest.MD5;
import com.gitee.apanlh.util.valid.Assert;
import com.gitee.apanlh.util.valid.ValidParam;
import com.ts.api.common.constant.api.ApiBizTypeEnum;
import com.ts.api.common.constant.api.ApiEnum;
import com.ts.api.common.redis.ApiMatchRedisKey;
import com.ts.api.exp.ApiMsgException;
import com.ts.api.module.api.entity.ApiUserRequest;
import com.ts.api.module.api.entity.bo.ApiBizMatchBO;
import com.ts.api.module.api.entity.bo.ApiDataExchangeBO;
import com.ts.api.module.api.entity.bo.ApiFilterParamBO;
import com.ts.api.module.api.entity.bo.ApiParameterBO;
import com.ts.api.module.api.entity.bo.ApiPreRequiredBO;
import com.ts.api.module.api.entity.bo.ApiRequiredFlowBO;
import com.ts.api.module.api.entity.bo.ApiUserRegisterBO;
import com.ts.api.module.api.entity.po.ApiKeyPO;
import com.ts.api.module.api.entity.vo.ReqApiParameterVO;
import com.ts.api.module.api.entity.vo.RespV2ApiApplyVO;
import com.ts.api.module.api.entity.vo.RespV2ApiDataExchangeVO;
import com.ts.api.module.api.service.ApiBizApplyService;
import com.ts.api.module.api.service.ApiBizDataExchangeService;
import com.ts.api.module.api.service.ApiBizRequiredService;
import com.ts.api.module.api.service.ApiMsgV2CallService;
import com.ts.api.module.api.service.ApiUserRegister;
import com.ts.api.module.channel.entity.po.ChannelUserFormFieldPO;
import com.ts.api.module.channel.entity.po.ChannelUserRegisterPO;
import com.ts.api.module.channel.service.ChannelFormService;
import com.ts.api.module.match.plan.internal.distribute.model.PlanDistributeField;
import com.ts.api.module.match.plan.internal.distribute.model.PlanDistributePhoneMd5Field;
import com.ts.api.module.product.entity.po.ProductApplyFlowPO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ApiMsgV2CallServiceImpl implements ApiMsgV2CallService {

    @Autowired
    private ApiBizRequiredService apiBizRequiredService;
    @Autowired
    private ApiBizDataExchangeService apiBizDataExchangeService;
    @Autowired
    private ApiBizApplyService apiBizApplyService;
    @Autowired
    private ApiUserRegister apiUserRegister;
    @Autowired
    private ChannelFormService channelFormService;

    @Override
    public RespV2ApiDataExchangeVO dataExchange(ApiKeyPO apiKeyPO, ReqApiParameterVO reqApiParameterVO) throws Exception {
        //  1.撞库前置校验-创建正常计划类型匹配（机构、平台）
        ApiBizMatchBO normalPlan = ApiBizMatchBO.createNormalPlan(true);
        ApiPreRequiredBO apiPreRequiredBO = ApiPreRequiredBO.create(reqApiParameterVO, ApiBizTypeEnum.DATA_EXCHANGE, null, normalPlan);
        ApiParameterBO apiParameterBO = apiBizRequiredService.preRequiredParam(apiPreRequiredBO);

        //  2.撞库匹配
        ApiDataExchangeBO apiDataExchangeBO = apiBizDataExchangeService.dataExchange(apiParameterBO);
        PlanDistributeField planDistributeField = apiDataExchangeBO.getPlanDistributeField();

        //  3.将撞库流程id保存至redis中
        PlanDistributePhoneMd5Field phoneMd5Field = planDistributeField.getPhoneMd5Field();
        String reqId = phoneMd5Field.getReqId();
        String key = ApiMatchRedisKey.getKey(reqId, phoneMd5Field.getPhoneMd5());

        //  4.下游非返回则设置phoneMd5作为value，否则返回apply作为value
        if (ValidParam.isEmpty(phoneMd5Field.getApplyId())) {
            ApiMatchRedisKey.API_CHANNEL_DATA_EXCHANGE_REQ_ID.setForMinutes(key, phoneMd5Field.getPhoneMd5(), 10);
        } else {
            ApiMatchRedisKey.API_CHANNEL_DATA_EXCHANGE_REQ_ID.setForMinutes(key, phoneMd5Field.getApplyId(), 10);
        }
        //  返回实体
        return RespV2ApiDataExchangeVO.create(apiDataExchangeBO, apiKeyPO);
    }

    @Override
    public RespV2ApiApplyVO apply(ApiKeyPO apiKeyPO, ReqApiParameterVO reqApiParameterVO) {
        //  1.查询是否渠道存在该流程
        ApiUserRequest apiUserRequest = reqApiParameterVO.getApiUserRequest();
        String phone = apiUserRequest.getPhone();
        Assert.isNotEmptyThrows(phone, new ApiMsgException(ApiEnum.API_REQUIRED_PARAM_NULL.format("phone")));
        String phoneMd5 = MD5.create().digestToHex(phone);

        ApiRequiredFlowBO apiRequiredFlowBO = ApiRequiredFlowBO.createByApiClientId(phoneMd5, apiKeyPO.getApiClientId());
        ProductApplyFlowPO productApplyFlowPO = apiBizRequiredService.requiredSucDataExchangeFlow(apiRequiredFlowBO);
        Assert.isNotNullThrows(productApplyFlowPO, new ApiMsgException(ApiEnum.API_APPLY_FLOW_ERROR));

        //  2.进件-前置参数验证
        ApiFilterParamBO apiFilterParamBO = ApiFilterParamBO.create("applyId");
        ApiBizMatchBO normalPlanApply = ApiBizMatchBO.createNormalPlanApply();
        ApiPreRequiredBO apiPreRequiredBO = ApiPreRequiredBO.create(reqApiParameterVO, ApiBizTypeEnum.APPLY, apiFilterParamBO, normalPlanApply);
        ApiParameterBO apiParameterBO = apiBizRequiredService.preRequiredParam(apiPreRequiredBO);

        //  3.注册用户
        ApiUserRegisterBO apiUserRegisterBO = apiUserRegister.applyUserRegister(apiParameterBO, productApplyFlowPO);

        //  4.下游回调授权页面（对方页面）-> 查询redis中是否存在平台下游分发 -> 存在则进件下游平台渠道
        if (ValidParam.isNotEmpty(apiKeyPO.getApiPullApplyNotifyUrl())) {
            String applyNoticeFlowKey = ApiMatchRedisKey.getApplyNoticeFlowKey(apiKeyPO.getApiClientId(), productApplyFlowPO.getLoanProductPlanId(), phoneMd5);

            //  有可能上游超时进件，无法获取到key
            if (ValidParam.isNull(ApiMatchRedisKey.API_CHANNEL_APPLY_NOTICE_FLOW.get(applyNoticeFlowKey))) {
                throw new ApiMsgException(ApiEnum.API_NOTICE_APPLY_TIMEOUT);
            }

            //  获取用户信息
            ChannelUserRegisterPO userRegisterPO = apiUserRegisterBO.getUserRegisterPO();
            List<ChannelUserFormFieldPO> listUserForm = channelFormService.listUserFormField(userRegisterPO.getId());

            //  转换分发对象
            ApiUserRequest copyApiUserRequest = ApiUserRequest.convert(userRegisterPO, listUserForm);
            apiBizApplyService.apply(copyApiUserRequest, apiParameterBO, productApplyFlowPO);

            //  获取撞库成功返回的请求id
            String key = ApiMatchRedisKey.getKey(productApplyFlowPO.getReqId().toString(), phoneMd5);
            String applyId = ApiMatchRedisKey.API_CHANNEL_DATA_EXCHANGE_REQ_ID.get(key, String.class);
            //  返回下游平台返回的applyId
            return RespV2ApiApplyVO.create(applyId);
        }
        //  5.我方回调页面则返回用户信息
        return RespV2ApiApplyVO.create(phoneMd5);
    }

    @Override
    public RespV2ApiDataExchangeVO dataExchangePhoneMask(ApiKeyPO apiKeyPO, ReqApiParameterVO reqApiParameterVO, Integer maskLen) throws Exception {
//        //  1.撞库前置校验-创建正常计划类型匹配（机构、平台）
//        ApiBizMatchBO normalPlan = ApiBizMatchBO.createNormalPlan(true);
//        ApiPreRequiredBO apiPreRequiredBO = ApiPreRequiredBO.create(reqApiParameterVO, ApiBizTypeEnum.DATA_EXCHANGE, null, normalPlan);
//        ApiParameterBO apiParameterBO = apiBizRequiredService.preRequiredParamPhoneMask(apiPreRequiredBO);
//
//        //  2.撞库匹配
//        ApiDataExchangeBO apiDataExchangeBO = apiBizDataExchangeService.dataExchangePhoneMask(apiParameterBO, maskLen);
//        PlanDistributeField planDistributeField = apiDataExchangeBO.getPlanDistributeField();
//
//        //  3.将撞库流程id保存至redis中
//        String reqId = planDistributeField.getReqId();
//        String key = ApiMatchRedisKey.getKey(reqId, planDistributeField.getPhoneMd5());
//
//        //  4.下游非返回则设置phoneMd5作为value，否则返回apply作为value
//        if (ValidParam.isEmpty(planDistributeField.getApplyId())) {
//            ApiMatchRedisKey.API_CHANNEL_DATA_EXCHANGE_REQ_ID.setForMinutes(key, planDistributeField.getPhoneMd5(), 10);
//        } else {
//            ApiMatchRedisKey.API_CHANNEL_DATA_EXCHANGE_REQ_ID.setForMinutes(key, planDistributeField.getApplyId(), 10);
//        }
//
//        //  返回实体
//        return RespV2ApiDataExchangeVO.create(apiDataExchangeBO, apiKeyPO);
        return null;
    }

    @Override
    public RespV2ApiApplyVO applyPhoneMask(ApiKeyPO apiKeyPO, ReqApiParameterVO reqApiParameterVO) {
        //  1.查询是否渠道存在该流程
        ApiUserRequest apiUserRequest = reqApiParameterVO.getApiUserRequest();
        String phone = apiUserRequest.getPhone();
        Assert.isNotEmptyThrows(phone, new ApiMsgException(ApiEnum.API_REQUIRED_PARAM_NULL.format("phone")));
        String phoneMd5 = MD5.create().digestToHex(phone);

        ApiRequiredFlowBO apiRequiredFlowBO = ApiRequiredFlowBO.createByApiClientId(phoneMd5, apiKeyPO.getApiClientId());
        ProductApplyFlowPO productApplyFlowPO = apiBizRequiredService.requiredSucDataExchangeFlow(apiRequiredFlowBO);
        Assert.isNotNullThrows(productApplyFlowPO, new ApiMsgException(ApiEnum.API_APPLY_FLOW_ERROR));

        //  2.进件-前置参数验证
        ApiFilterParamBO apiFilterParamBO = ApiFilterParamBO.create("applyId");
        ApiBizMatchBO normalPlanApply = ApiBizMatchBO.createNormalPlanApply();
        ApiPreRequiredBO apiPreRequiredBO = ApiPreRequiredBO.create(reqApiParameterVO, ApiBizTypeEnum.APPLY, apiFilterParamBO, normalPlanApply);
        ApiParameterBO apiParameterBO = apiBizRequiredService.preRequiredParamPhoneMask(apiPreRequiredBO);

        //  3.注册用户
        ApiUserRegisterBO apiUserRegisterBO = apiUserRegister.applyUserRegister(apiParameterBO, productApplyFlowPO);

        //  4.下游回调授权页面（对方页面）-> 查询redis中是否存在平台下游分发 -> 存在则进件下游平台渠道
        if (ValidParam.isNotEmpty(apiKeyPO.getApiPullApplyNotifyUrl())) {
            String applyNoticeFlowKey = ApiMatchRedisKey.getApplyNoticeFlowKey(apiKeyPO.getApiClientId(), productApplyFlowPO.getLoanProductPlanId(), phoneMd5);

            //  有可能上游超时进件，无法获取到key
            if (ValidParam.isNull(ApiMatchRedisKey.API_CHANNEL_APPLY_NOTICE_FLOW.get(applyNoticeFlowKey))) {
                throw new ApiMsgException(ApiEnum.API_NOTICE_APPLY_TIMEOUT);
            }

            //  获取用户信息
            ChannelUserRegisterPO userRegisterPO = apiUserRegisterBO.getUserRegisterPO();
            List<ChannelUserFormFieldPO> listUserForm = channelFormService.listUserFormField(userRegisterPO.getId());

            //  转换分发对象
            ApiUserRequest copyApiUserRequest = ApiUserRequest.convert(userRegisterPO, listUserForm);
            apiBizApplyService.apply(copyApiUserRequest, apiParameterBO, productApplyFlowPO);

            //  4.获取撞库成功返回的请求id
            String key = ApiMatchRedisKey.getKey(productApplyFlowPO.getReqId().toString(), phoneMd5);
            String applyId = ApiMatchRedisKey.API_CHANNEL_DATA_EXCHANGE_REQ_ID.get(key, String.class);
            return RespV2ApiApplyVO.create(applyId);
        }
        //  5.我方回调页面则返回用户信息
        return RespV2ApiApplyVO.create(phoneMd5);
    }
}
